ES6(Default Parameters、箭頭函式、Import 與 Export、Babel)


Posted by saffran on 2021-02-05

加上預設值:Default Parameters

default parameters 就是「預設值」的意思

「function」搭配預設值來使用

這裡是一個 repeat 函式

function repeat(str, times){
  return str.repeat(times)
}

console.log(repeat('love', 5))
// output: lovelovelovelovelove

在呼叫 repeat 函式時,如果參數 times 沒有寫,那麼參數 times 就會是 undefined,然後印出 repeat('love') 的結果也會是什麼都沒有

function repeat(str, times){
  console.log(times) // 把 times 印出來看看
  return str.repeat(times)
}

console.log(repeat('love'))

output:

undefined

設定參數的預設值

repeat 函式的參數 times 後方設定 = 5 的預設值,這樣,在呼叫 repeat 函式時如果沒有傳入 timestimes 就會是預設值(5)

function repeat(str, times = 5){
  console.log(times) // 把 times 印出來看看
  return str.repeat(times)
}

console.log(repeat('love'))

output:

5
lovelovelovelovelove

也可以把兩個參數 strtimes 都設定預設值
這樣,在呼叫 repeat 函式時,如果完全沒有傳入參數,就會都使用預設值

function repeat(str = 'hey', times = 3){
  return str.repeat(times)
}

console.log(repeat())
// output: heyheyhey

「解構」搭配預設值來使用

「預設值」也可以用在陣列、物件的解構

const obj = {
  a: 8,
  b: 9
}

const {a, b} = obj

console.log(a, b)
// output: 8 9

如果在宣告變數 obj 時,就沒有 a,那麼解構之後印出變數 a 就會是 undefined

const obj = {
  b: 9
}

const {a, b} = obj

console.log(a, b)
// output: undefined 9

設定變數的預設值

在解構時,可以幫變數 a 設定預設值 = 333
在宣告變數 obj 時,如果沒有 a,那麼印出來的變數 a就會是 333

const obj = {
  b: 9
}

const {a = 333, b} = obj // 幫變數 a 設定預設值

console.log(a, b)
// output: 333 9

但在宣告變數 obj 時,如果有 a,就不會使用預設值了

const obj = {
  a: 20
}

const {a = 333, b = 'lemon'} = obj // 幫變數 a 設定預設值

console.log(a, b)
// output: 20 lemon

宣告 Function 的新方式:箭頭函式 Arrow Function

在 ES5,宣告 function 的方式有兩種:

  • 第一種
    function test(n){
    return n * 2
    }
    
  • 第二種
    const test = function(n){
    return n * 2
    }
    

箭頭函式

在 ES6,有另一種宣告 function 的方式,也就是上方第二種的變化版:

省略 function 這個關鍵字

  • 把 function 這個關鍵字省略
  • (n) 後面加上一個箭頭符號 =>
const test = (n) => {
  return n * 2
}

省略參數的小括號

  • 如果只有傳入一個參數的話,參數的小括號可以省略掉
    const test = n => {
    return n * 2
    }
    

省略大括號、return

  • 如果在大括號內的程式碼只有要「return 一行」的話,就可以省略大括號和 return 這個關鍵字
    const test = n => n * 2
    
    如果想要把大括號加回去,記得也要把 return 加回去,不然 function 預設都會 return undefined

    可參考 箭頭函式出現 bug 的可能原因

箭頭函式的好處

使用箭頭函式的好處是:程式碼更簡潔、可讀性更高,尤其是在使用array 相關的 function 時更明顯

例如:
在使用 filter()map() 時,裡面都要傳入一個 function
ES5 的寫法是這樣:

let arr = [4, 5, 6, 7, 8]

console.log(
  arr
  .filter(function(value){
    return value > 4
  })
  .map(function(value){
    return value * 2
  })
)
// output: [ 10, 12, 14, 16 ]

ES6 的寫法是這樣:

  • 省略 function 這個關鍵字
  • 省略參數的小括號
  • 如果在大括號內的程式碼只有一行的話,就可以省略大括號和 return 這個關鍵字
let arr = [4, 5, 6, 7, 8]

console.log(
  arr
    .filter(value => value > 4)
    .map(value => value * 2)
)
// output: [ 10, 12, 14, 16 ]

Import 與 Export

關於 module 的輸出、引入,在 ES5 和 ES6 有什麼不一樣呢?

先複習一下 ES5 的輸出、引入

在 ES5,module.exportsrequire 是「成對使用」的

我現在有兩個檔案,分別是:index.js 和 utils.js

輸出 module.exports

在 utils.js 把 module 輸出

function add(a, b){
  return a + b
}

module.exports = add

引入 require

然後在 index.js 把 module 引入

let myModule = require('./utils')

console.log(myModule(8, 9))
// output: 17

ES6 的輸出、引入

在 ES6,會有不同的語法來輸出、引入 module

是「成對使用」的

輸出 export

export 這個關鍵字可以同時把多個東西輸出

寫法一 export

在 utils.js
假設我想要輸出 add 函式,就在 add 函式前面加上 export這個關鍵字即可

假設我也想要輸出 PI 這個變數,也一樣就在變數最前面加上 export 這個關鍵字即可

export function add(a, b){
  return a + b
}

export const PI = 3.14

寫法二 export{}

在 utils.js
假設我想要輸出 add 函式和 PI 變數,就在下面寫一個 export 加大括號,然後在大括號裡面寫上 add 函式和 PI 變數

注意!這裡的 export {add, PI} 並不是一個物件

function add(a, b){
  return a + b
}

const PI = 3.14

export {
  add,
  PI
}

引入 import { add, PI } from './utils.js'

import { add, PI } from './utils.js'

console.log(add(8, 9), PI)
// output: 17 3.14

如果直接用 node index.js 執行的話,會出現錯誤:它認不得 import 這個東西
原因是:
目前 Node.js 的版本,還沒辦法原生的支援 import 語法

因此,要用 npx babel-node index.js 來執行 index.js

用別的名稱輸出(使用 as 這個關鍵字)

假設,我想要用 addFunction 這個新的名稱來輸出 add 函式

在 utils.js 的 export 使用 add as addFunction

as 這個關鍵字來幫 add 函式取別名
例如說 export { add as addFunction }

function add(a, b){
  return a + b
}

const PI = 3.14

export {
  add as addFunction,
  PI
}

那在 index.js 引入時,就要使用新的名稱 addFunction

import { addFunction, PI } from './utils.js'

console.log(addFunction(8, 9), PI)
// output: 17 3.14

用別的名稱引入(使用 as 這個關鍵字)

在 index.js 的 import 使用 addFunction as plus

在引入時,如果覺得 addFunction 這個名稱太長了,可以使用 as 來取另一個名稱

例如,我把 addFunction 重新取名叫做 plus

import { addFunction as plus, PI } from './utils.js'

console.log(plus(8, 9), PI)
// output: 17 3.14

* 把所有東西一次引入進來(此方法很常用)

utils.js 的輸出:

function add(a, b){
  return a + b
}

const PI = 3.14

export {
  add as addFunction,
  PI
}

在 index.js 引入時,如果不想要把每一個要引入的東西都很明確地寫出來,可以用 * 把 utils.js 裡面的所有東西全部都 import 進來

使用這句 import * as hello from './utils.js' 即可
這句的意思是:
把 utils.js 裡面的所有東西,用 hello 這個 module 名稱(自己隨意取)引入到 index.js 裡面

在程式中,* 通常代表「所有東西」的意思

因此,

  • 要使用 add 函式時,就要用 hello.addFunction(8, 9) 這樣子
  • 要使用 PI 時,就要用 hello.PI 這樣子
import * as hello from './utils.js'

console.log(hello.addFunction(8, 9), hello.PI)
// output: 17 3.14

export default

default 就是「預設值」的意思

在 utils.js 輸出時,

  • add 函式前面加上 export default
  • PI 前面只有寫 export 而已
export default function add(a, b){
  return a + b
}

export const PI = 3.14

輸出時有 default 這個關鍵字,引入就不需要大括號(因為:預設就會引入)

因為 add 函式在輸出時,有加上 default
所以,在 index.js 用 import 引入時,add 不需要加大括號,直接寫上 add 就可以把 add 函式引入了

import add from './utils.js'

console.log(add(8, 9))
// output: 17

輸出時沒有 default 這個關鍵字,引入就需要大括號

因為 PI 在輸出時,沒有加上 default
所以,在 index.js 用 import 引入時,PI 需要加大括號

import add, {PI} from './utils.js'

console.log(add(8, 9), PI)
// output: 17 3.14

default 來預設引入,背後的原理可以看成是這樣:

import {default as add, PI} from './utils.js'

console.log(add(8, 9), PI)

下面這兩句是一樣的意思:

import {default as add} from './utils.js'
import add from './utils.js'

Babel 簡介與基本使用方法

Babel 是現代前端開發中,一個不可或缺的工具

如果我想用某個語法,但目前這個語法在舊的瀏覽器還沒被支援,這時該怎麼辦?

就去開發一個工具,把新語法轉換成舊的語法,讓舊的瀏覽器都可以支援

因為前端的發展速度比「瀏覽器更新的速度」要快很多,因此才會需要這麼多前端工具來解決舊瀏覽器支援度或是其他問題

而 Babel 就是一個這樣的前端工具:
輸入 ES6/ES7/ES8 的語法,經過 Babel 編譯之後,轉換成 ES5(如果是在 IE7/IE8 這種超舊的瀏覽器,甚至會轉換成 ES4)

ES6/ES7/ES8 => Babel => ES4/ES5

假設,專案資料夾的檔案有:

  • utils.js (輸出)
    ```javascript=
    export default function add(a, b){
    return a + b
    }

export const PI = 3.14

* index.js (輸入)
```javascript=
import add from './utils.js'

console.log(add(8, 9))

如果 Node.js 的版本在 13.0 以下,輸入指令 node index.js 去執行的話,就會出現錯誤:它還無法支援 import 這個語法

這時,就需要 Babel 的幫忙了

babel-node

Babel 的用法有很多種,這裡要介紹的是 babel-node

babel-node 的指令跟 node 很像(把它當成 node 來用就好),跟 node 的差別在於:babel-node 可以支援更多新的語法,但 node 不行

注意!因為 babel-node 的效能不太好,所以不要用在 production 上面,babel-node 只適合用在自己個人開發上(自己玩玩的)

如果要把 Babel 用在 production 上的話,可以參考這些範例,通常都會先 compile 完之後,再直接用 node 去執行 compile 完的那些檔案

安裝 @babel/core 和 @babel/node

在專案資料夾底下,輸入指令 npm install --save-dev @babel/core @babel/node 來安裝 @babel/core 和 @babel/node

  • 裝好 @babel/core 和 @babel/node 之後,就可以輸入指令 npx babel-node 來進入「可以輸入程式碼」的模式

這時,當我輸入指令 npx babel-node index.js 來執行 index.js,還是會出現錯誤:無法支援 import 語法

原因是:
Babel 還需要設定一些東西,才能支援這些新的語法

安裝 @babel/preset-env

設定方式是:
輸入指令 npm install --save @babel/preset-env 來安裝 @babel/preset-env
preset 裡面是一些設定,會告訴 Babel 關於語法轉換的事情(要把多新的語法,轉換成多舊的語法)

一定要裝 @babel/preset-env 套件,Babel 才會知道要幫我把 ES6 轉換成 ES5 的語法

這時,當我輸入指令 npx babel-node index.js 來執行 index.js,還是一樣會出現錯誤:無法支援 import 語法

原因是:
我只是安裝了 @babel/preset-env 套件,但我還沒跟 Babel 說「我要使用 @babel/preset-env 這個套件」

要怎麼跟 Babel 說「我要使用 @babel/preset-env 這個套件」呢?作法如下:

  1. 新增一個檔案叫做 .babelrc (會是一個隱藏檔案,要放在專案資料夾的根目錄)
  2. 打開 .babelrc,在裡面寫上:
    {
    "presets": ["@babel/preset-env"]
    }
    

意思就是:我的 preset 要使用的是 @babel/preset-env 這個套件

這時,當我輸入指令 npx babel-node index.js 來執行 index.js,就可以成功執行了

總結一下 babel-node 的設定步驟:

  1. 安裝三個必要套件:npm install --save-dev @babel/core @babel/node @babel/preset-env
  2. 新增 .babelrc 檔案
  3. 在 .babelrc 檔案填入內容,告訴 babel 要用這個 preset:
    {
    "presets": ["@babel/preset-env"]
    }
    
    這樣,就可以用 npx babel-node index.js 來執行了!

更多 ES6 的語法

想查詢更多 ES6 新增的語法,可參考 es6-cheatsheet


#javascript







Related Posts

Geolocation based Speedometer and Compass

Geolocation based Speedometer and Compass

Sequelize CLI 實戰

Sequelize CLI 實戰

Linkedin Java 檢定題庫  try catch 流程

Linkedin Java 檢定題庫 try catch 流程


Comments